<?php
// +-----------------------------------------------------------------------------------------------
// | 简易CMS
// +-----------------------------------------------------------------------------------------------
// | [请手动修改文件描述]
// +-----------------------------------------------------------------------------------------------
// | Author: IT果农 <htmambo@163.com> <http://www.haolie.net>
// +-----------------------------------------------------------------------------------------------
// | Version $Id: OpenAuth.class.php 9 2016-09-17 11:22:17Z IT果农 <htmambo@163.com> $
// +-----------------------------------------------------------------------------------------------

namespace CMS\Wechat;

use CMS\Wechat\WechatErrCode;
use CMS\Wechat\Auth;
/**
 * JSAPI支付——H5网页端调起登陆,支付接口
 * 文档:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
 */
class OpenAuth extends Auth {
    /**
     * 微信api根路径
     * @var string
     */
    var $apiURL = 'https://api.weixin.qq.com/sns';

    /**
     * 请求code的链接
     * @var string
     */
    private $requestCodeURL = 'https://open.weixin.qq.com/connect/oauth2/authorize';
    var $code; //code码，用以获取openid
    var $openid; //用户的openid
    var $parameters; //jsapi参数，格式为json
    var $prepay_id; //使用统一支付接口得到的预支付id
    var $curl_timeout; //curl超时时间
    var $unionid; //用户的unionid,暂时没用到
    var $userinfo; //微信用户信息,snsapi_userinfo方式授权可获得
    var $access_token; //access_token

    /**
     * 生成请求CODE的链接
     * @param string $redirect_uri 回跳地址
     * @param string $state
     * @param string $scope
     * @return string
     */
    public function getRequestCodeURL($redirect_uri, $state = null, $scope = 'snsapi_userinfo') {
        $query = array(
            'appid'         => $this->appId,
            'redirect_uri'  => $redirect_uri,
            'response_type' => 'code',
            'scope'         => $scope,
        );

        if (!is_null($state) && preg_match('/[a-zA-Z0-9]+/', $state)) {
            $query['state'] = $state;
        }

        $query = http_build_query($query);
        return "{$this->requestCodeURL}?{$query}#wechat_redirect";
    }

    /**
     * 获取access_token，用于后续接口访问
     * @return array access_token信息，包含 token 和有效期
     */
    public function getAccessToken($code = null, $force = false) {
        $param = array(
            'appid'  => $this->appId,
            'secret' => $this->appSecret
        );
        $token = false;
        $cachekey = 'wechat_token_' . $this->appId . '_open';
        if (!$force) {
            $token = cache($cachekey);
            if (!$token || $token['expires_in'] <= NOW_TIME) {
                $token = false;
            }
        }
        if (!$token) {
            $param['code'] = $code;
            $param['grant_type'] = 'authorization_code';
            $url = "{$this->apiURL}/oauth2/access_token";
            $token = self::http($url, $param);
            $token = json_decode($token, true);
            if (is_array($token) && isset($token['errcode'])) {
                throw new \Exception($token['errmsg']);
            }
            $token['expires_in'] += NOW_TIME - 100;       //缓存时间，这个由微信返回，这里加上当前时间戳
            cache($cachekey, $token);
        }
        if (is_array($token)) {
            $this->accessToken = $token['access_token'];
            return $token['access_token'];
        } else {
            throw new \Exception('获取微信access_token失败！');
        }
    }

    /**
     * 使用code来获取用户信息
     */
    function getUserInfoByCode($code = '') {
        $param = array(
            'appid'      => $this->appId,
            'secret'     => $this->appSecret,
            'code'       => $code,
            'grant_type' => 'authorization_code'
        );
        $url = "{$this->apiURL}/oauth2/access_token";
        $result = self::http($url, $param);
        $result = json_decode($result, true);
        if (!is_array($result) || isset($result['errcode'])) {
            throw new \Exception($result['errmsg']);
        }
        $this->accessToken = $result['access_token'];
        $data = $this->getUserInfo($result['openid']);
        if(!$data || !$data['openid']) {
            $data = $result;
        }
        return $data;
    }

    /**
     * 获取授权用户信息
     * @param  string $openid 用户的OpenID
     * @param  string $lang   指定的语言
     * @return array          用户信息数据，具体参见微信文档
     */
    public function getUserInfo($openid, $lang = 'zh_CN') {
        if (!$this->accessToken) {
            $this->accessToken = $this->getAccessToken(NULL, true);
        }
        $query = array(
            'access_token' => $this->accessToken,
            'openid'       => $openid,
            'lang'         => $lang,
        );
        return $this->api('userinfo', '', 'GET', $query);
    }
}
